#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using System.Collections.Generic;
using System.Xml;
using System.Xml.Xsl;
using System.IO;
using System.Xml.XPath;

namespace Newtonsoft.Utilities.Xml
{
  public static class XslUtils
  {
    public static XmlTextReader GetTemplateFromCache(string xslTemplatePath, string templateName)
    {
      string filePath = xslTemplatePath + templateName;
      StringReader sr = new StringReader(File.ReadAllText(filePath));

      return new XmlTextReader(sr);
    }

    public static void TransformNodeInnerXml(XmlNode element, XmlReader xslTemplate)
    {
      XmlTextReader reader = new XmlTextReader(new StringReader(element.InnerXml));
      element.InnerXml = TransformXml(reader, xslTemplate).ReadToEnd();
    }

    public static StreamReader TransformXml(XmlReader xml, XmlReader xsl)
    {
      XPathNavigator navigator = new XPathDocument(xml).CreateNavigator();
      return TransformXml(navigator, xsl, null);
    }

    public static StreamReader TransformXml(XmlReader xml, XmlReader xsl, XsltArgumentList args, XmlResolver resolver)
    {
      XPathNavigator navigator = new XPathDocument(xml).CreateNavigator();
      return TransformXml(navigator, xsl, args, resolver);
    }

    public static StreamReader TransformXml(XmlReader xml, XmlReader xsl, XsltArgumentList args)
    {
      XPathNavigator navigator = new XPathDocument(xml).CreateNavigator();
      return TransformXml(navigator, xsl, args);
    }

    public static StreamReader TransformXml(XPathNavigator xmlXPathDocument, XmlReader xsl, XsltArgumentList args)
    {
      return TransformXml(xmlXPathDocument, xsl, args, new XmlUrlResolver());
    }

    public static StreamReader TransformXml(XPathNavigator xmlXPathDocument, XmlReader xsl, XsltArgumentList args, XmlResolver resolver)
    {
      XPathNavigator navigator = new XPathDocument(xsl).CreateNavigator();
      XslCompiledTransform transform = new XslCompiledTransform();
      transform.Load(navigator, XsltSettings.Default, resolver);
      MemoryStream ms = new MemoryStream();
      transform.Transform(xmlXPathDocument, args, ms);
      ms.Seek(0, SeekOrigin.Begin);

      return new StreamReader(ms);
    }

    public static StreamReader TransformXml(XmlReader xslTemplate, IDictionary<string, object> parameters)
    {
      XmlDocument doc = new XmlDocument();
      doc.AppendChild(doc.CreateElement("DocumentRoot"));
      XsltArgumentList args = new XsltArgumentList();
      if (parameters != null)
      {
        foreach (KeyValuePair<string, object> nameValue in parameters)
        {
          args.AddParam(nameValue.Key, string.Empty, nameValue.Value);
        }
      }

      return TransformXml(doc.CreateNavigator(), xslTemplate, args);
    }

    public static StreamReader TransformXml(XmlReader xslTemplate, XsltArgumentList args)
    {
      XmlDocument doc = new XmlDocument();
      doc.AppendChild(doc.CreateElement("DocumentRoot"));

      return TransformXml(doc.CreateNavigator(), xslTemplate, args);
    }

    public static StreamReader TransformXml(string xslTemplatePath, XsltArgumentList args)
    {
      using (StreamReader sr = new StreamReader(xslTemplatePath))
      using (XmlTextReader xmlReader = new XmlTextReader(sr))
      {
        return TransformXml(xmlReader, args);
      }
    }
  }
}